<?php

defined('SYSPATH') or die('Access error!');
/**
 * Text辅助类 
 */
class Text {

	/**
	 *  单位对应表
	 */
	public static $units = array(
		1000000000 => 'billion',
		1000000    => 'million',
		1000       => 'thousand',
		100        => 'hundred',
		90 => 'ninety',
		80 => 'eighty',
		70 => 'seventy',
		60 => 'sixty',
		50 => 'fifty',
		40 => 'fourty',
		30 => 'thirty',
		20 => 'twenty',
		19 => 'nineteen',
		18 => 'eighteen',
		17 => 'seventeen',
		16 => 'sixteen',
		15 => 'fifteen',
		14 => 'fourteen',
		13 => 'thirteen',
		12 => 'twelve',
		11 => 'eleven',
		10 => 'ten',
		9  => 'nine',
		8  => 'eight',
		7  => 'seven',
		6  => 'six',
		5  => 'five',
		4  => 'four',
		3  => 'three',
		2  => 'two',
		1  => 'one',
	);

	/**
	 *   针对于单词截取
	 *
	 *     $text = Text::limit_words($text);
	 *
	 * @param   string  $str        需要截取的字符串（主要是针对单词）
	 * @param   integer $limit      需要的长度
	 * @param   string  $end_char   结尾的展示例如：...
	 * @return  string
	 */
	public static function limit_words($str, $limit = 100, $end_char = NULL)
	{
		$limit = (int) $limit;
		$end_char = ($end_char === NULL) ? '…' : $end_char;

		if (trim($str) === '')
			return $str;

		if ($limit <= 0)
			return $end_char;

		preg_match('/^\s*+(?:\S++\s*+){1,'.$limit.'}/u', $str, $matches);

		return rtrim($matches[0]).((strlen($matches[0]) === strlen($str)) ? '' : $end_char);
	}

	/**
	 * 截取的个数中文也是1个
	 *
	 *     $text = Text::limit_chars($text);
	 *
	 * @param   string  $str            需要的字符串
	 * @param   integer $limit          截取的个数
	 * @param   string  $end_char       结尾展示例如：...
	 * @return  string
	 * @uses    UTF8::strlen
	 */
	public static function limit_chars($str, $limit = 100, $end_char = NULL, $preserve_words = FALSE)
	{
		$end_char = ($end_char === NULL) ? '...' : $end_char;

		$limit = (int) $limit;

		if (trim($str) === '' OR UTF8::strlen($str) <= $limit)
			return $str;

		if ($limit <= 0)
			return $end_char;

		if ($preserve_words === FALSE)
			return rtrim(UTF8::substr($str, 0, $limit)).$end_char;

		if ( ! preg_match('/^.{0,'.$limit.'}\s/us', $str, $matches))
			return $end_char;

		return rtrim($matches[0]).((strlen($matches[0]) === strlen($str)) ? '' : $end_char);
	}

	/**
	 * 在两个或者多个所给的变量间交替输出
	 *
	 *     echo Text::alternate('one', 'two'); // "one"
	 *     echo Text::alternate('one', 'two'); // "two"
	 *     echo Text::alternate('one', 'two'); // "one"
	 *
	 *
	 * @param   string  $str,...    需要的变量
	 * @return  string
	 */
	public static function alternate()
	{
		static $i;

		if (func_num_args() === 0)
		{
			$i = 0;
			return '';
		}

		$args = func_get_args();
		return $args[($i++ % count($args))];
	}

	/**
	 * 根据所给的类型（例如数字 字符） 生成需要的随机数
	 *     $str = Text::random(); 
	 * @param   string  $type   所给的类型
	 * @param   integer $length 生成的长度
	 * @return  string
	 * @uses    UTF8::split
	 */
	public static function random($type = NULL, $length = 8)
	{
		if ($type === NULL)
		{
			$type = 'alnum';
		}

		$utf8 = FALSE;

		switch ($type)
		{
			case 'alnum':
				$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
			break;
			case 'alpha':
				$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
			break;
			case 'hexdec':
				$pool = '0123456789abcdef';
			break;
			case 'numeric':
				$pool = '0123456789';
			break;
			case 'nozero':
				$pool = '123456789';
			break;
			case 'distinct':
				$pool = '2345679ACDEFHJKLMNPRSTUVWXYZ';
			break;
			default:
				$pool = (string) $type;
				$utf8 = ! UTF8::is_ascii($pool);
			break;
		}

		$pool = ($utf8 === TRUE) ? UTF8::str_split($pool, 1) : str_split($pool, 1);

		$max = count($pool) - 1;

		$str = '';
		for ($i = 0; $i < $length; $i++)
		{
			$str .= $pool[mt_rand(0, $max)];
		}

		if ($type === 'alnum' AND $length > 1)
		{
			if (ctype_alpha($str))
			{
				$str[mt_rand(0, $length - 1)] = chr(mt_rand(48, 57));
			}
			elseif (ctype_digit($str))
			{
				$str[mt_rand(0, $length - 1)] = chr(mt_rand(65, 90));
			}
		}

		return $str;
	}

	/**
	 * 单词的首字母大写
	 *      $str = Text::ucfirst('content-type'); // returns "Content-Type" 
	 * @return  string
	 */
	public static function ucfirst($string, $delimiter = '-')
	{
		return implode($delimiter, array_map('ucfirst', explode($delimiter, $string)));
	}

	/**
	 * 减少字符串中的多个单斜线斜线。
	 *
	 *     $str = Text::reduce_slashes('foo//bar/baz'); // "foo/bar/baz"
	 *
	 * @param   string  $str    需要转化的字符串
	 * @return  string
	 */
	public static function reduce_slashes($str)
	{
		return preg_replace('#(?<!:)//+#', '/', $str);
	}

	/**
	 *    敏感词转换
	 *
	 *     // 例如得到： "What the #####, man!"
	 *     echo Text::censor('What the frick, man!', array(
	 *         'frick' => '#####',
	 *     ));
         *     //中文：我爱** 
         *   echo Text::censor('我爱中国', array('中','国'),'*');
	 *
	 * @param   string  $str                   需要转换的字符串
	 * @param   array   $badwords               需要被换掉的字符（可以是关联数组）
	 * @param   string  $replacement            用于替换的字符
	 * @return  string
	 * @uses    UTF8::strlen
	 */
	public static function censor($str, $badwords, $replacement = '#', $replace_partial_words = TRUE)
	{
		foreach ( (array) $badwords as $key => $badword)
		{
			$badwords[$key] = str_replace('\*', '\S*?', preg_quote( (string) $badword));
		}

		$regex = '('.implode('|', $badwords).')';

		if ($replace_partial_words === FALSE)
		{
			$regex = '(?<=\b|\s|^)'.$regex.'(?=\b|\s|$)';
		}

		$regex = '!'.$regex.'!ui';

		if (UTF8::strlen($replacement) == 1)
		{
			$regex .= 'e';
			return preg_replace($regex, 'str_repeat($replacement, UTF8::strlen(\'$1\'))', $str);
		}

		return preg_replace($regex, $replacement, $str);
	}

	/**
	 * 查找的文本，它是类似的一组词。
	 *
         *    //字符 ：fr
	 *     $match = Text::similar(array('fred', 'fran', 'free'); 
         *    //中文 ：我爱
         *     echo Text::similar(array('我爱中国','我爱外国','我爱澳大利亚'));
	 *
	 * @param   array   $words  需要查询的
	 * @return  string
	 */
	public static function similar(array $words)
	{
		$word = current($words);

		for ($i = 0, $max = strlen($word); $i < $max; ++$i)
		{
			foreach ($words as $w)
			{
				if ( ! isset($w[$i]) OR $w[$i] !== $word[$i])
					break 2;
			}
		}

		return substr($word, 0, $i);
	}

	/**
	 * 自动给email或者是a标签生成链接
	 *
	 *     echo Text::auto_link($text);
	 *
	 * @param   string  $text   需要生成的字符串
	 * @return  string
	 */
	public static function auto_link($text)
	{
		return Text::auto_link_urls(Text::auto_link_emails($text));
	}

	/**
	 *
	 *     echo Text::auto_link_urls($text);
	 *
	 *
	 * @param   string  $text  
	 * @return  string
	 * @uses    HTML::anchor
	 */
	public static function auto_link_urls($text)
	{
		//查找替换所有 http/https/ftp/ftps 类似这种不属于现有的HTML锚链接
		$text = preg_replace_callback('~\b(?<!href="|">)(?:ht|f)tps?://[^<\s]+(?:/|\b)~i', 'Text::_auto_link_urls_callback1', $text);

		// 查找替换所有 www.links.com (without http://)
		return preg_replace_callback('~\b(?<!://|">)www(?:\.[a-z0-9][-a-z0-9]*+)+\.[a-z]{2,6}[^<\s]*\b~i', 'Text::_auto_link_urls_callback2', $text);
	}

	protected static function _auto_link_urls_callback1($matches)
	{
		return HTML::anchor($matches[0]);
	}

	protected static function _auto_link_urls_callback2($matches)
	{
		return HTML::anchor('http://'.$matches[0], $matches[0]);
	}

	/**
	 * 生成email链接  html类也有
	 *
	 *     echo Text::auto_link_emails($text);
	 *
	 *
	 * @param   string  $text   
	 * @return  string
	 * @uses    HTML::mailto
	 */
	public static function auto_link_emails($text)
	{
		return preg_replace_callback('~\b(?<!href="mailto:|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b(?!</a>)~i', 'Text::_auto_link_emails_callback', $text);
	}

	protected static function _auto_link_emails_callback($matches)
	{
		return HTML::mailto($matches[0]);
	}

	/**
	 * 生成自动的p或者是br标记
	 *
	 *     echo Text::auto_p($text);
	 * @return  string
	 */
	public static function auto_p($str, $br = TRUE)
	{
		if (($str = trim($str)) === '')
			return '';

		$str = str_replace(array("\r\n", "\r"), "\n", $str);

		$str = preg_replace('~^[ \t]+~m', '', $str);
		$str = preg_replace('~[ \t]+$~m', '', $str);

		if ($html_found = (strpos($str, '<') !== FALSE))
		{
			$no_p = '(?:p|div|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))';

			$str = preg_replace('~^<'.$no_p.'[^>]*+>~im', "\n$0", $str);
			$str = preg_replace('~</'.$no_p.'\s*+>$~im', "$0\n", $str);
		}

		$str = '<p>'.trim($str).'</p>';
		$str = preg_replace('~\n{2,}~', "</p>\n\n<p>", $str);

		if ($html_found !== FALSE)
		{
			$str = preg_replace('~<p>(?=</?'.$no_p.'[^>]*+>)~i', '', $str);
			$str = preg_replace('~(</?'.$no_p.'[^>]*+>)</p>~i', '$1', $str);
		}

		if ($br === TRUE)
		{
			$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br />\n", $str);
		}

		return $str;
	}

	/**
	 * 转换文件的大小的单位
	 *
	 *     echo Text::bytes(filesize($file));
	 *
	 * @param   integer $bytes     
	 * @param   string  $force_unit 
	 * @param   string  $format     
	 * @param   boolean $si         
	 * @return  string
	 */
	public static function bytes($bytes, $force_unit = NULL, $format = NULL, $si = TRUE)
	{
		$format = ($format === NULL) ? '%01.2f %s' : (string) $format;

		if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE)
		{
			$units = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB');
			$mod   = 1024;
		}
		else
		{
			$units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
			$mod   = 1000;
		}

		if (($power = array_search( (string) $force_unit, $units)) === FALSE)
		{
			$power = ($bytes > 0) ? floor(log($bytes, $mod)) : 0;
		}

		return sprintf($format, $bytes / pow($mod, $power), $units[$power]);
	}


	/**
	 * 最后两个词之间的空格插入&nbsp;。
	 *
	 *     echo Text::widont($text);
	 *
	 * @param   string  $str
	 * @return  string
	 */
	public static function widont($str)
	{
		$str = rtrim($str);
		$space = strrpos($str, ' ');

		if ($space !== FALSE)
		{
			$str = substr($str, 0, $space).'&nbsp;'.substr($str, $space + 1);
		}

		return $str;
	}
        
        public static function is_email($string){
             return strlen($string) > 6 && strlen($string) <= 32 && preg_match("/^([A-Za-z0-9\-_.+]+)@([A-Za-z0-9\-]+[.][A-Za-z0-9\-.]+)$/", $string);
        }

}
